﻿using OrBitDataModule.CustomEventHandler;
using OrBitDataModule.Protocol;
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;

namespace OrBitDataModule.Adaptor
{
    public class DelayFileSystemWatcher
    {
        private bool isPaused = true;
        private readonly Timer m_Timer;
        private readonly Int32 m_TimerInterval;
        private readonly System.IO.FileSystemWatcher m_FileSystemWatcher;
        private readonly Dictionary<string, FileSystemEventArgs> m_ChangedFiles = new Dictionary<string, FileSystemEventArgs>();


        public event EventHandler<ProcessedFileSystemEventArgs> OnFileSystem_Changed;

        public DelayFileSystemWatcher(string path, string filter, int timerInterval, bool includeSubdirectories)
        {
            m_Timer = new Timer(OnTimer, null, Timeout.Infinite, Timeout.Infinite);
            m_FileSystemWatcher = new System.IO.FileSystemWatcher(path, filter.Trim());
            m_FileSystemWatcher.NotifyFilter = NotifyFilters.FileName | NotifyFilters.LastWrite | NotifyFilters.CreationTime;
            m_FileSystemWatcher.Created += fileSystemWatcher_Changed;
            m_FileSystemWatcher.Changed += fileSystemWatcher_Changed;
            m_FileSystemWatcher.Deleted += fileSystemWatcher_Changed;
            m_FileSystemWatcher.Renamed += fileSystemWatcher_Changed;
            m_FileSystemWatcher.EnableRaisingEvents = true;
            m_FileSystemWatcher.IncludeSubdirectories = includeSubdirectories;
            m_TimerInterval = timerInterval;
        }

        private void fileSystemWatcher_Changed(object sender, FileSystemEventArgs e)
        {
            if (!isPaused)
            {
                lock (m_ChangedFiles)
                {
                    if (!m_ChangedFiles.ContainsKey(e.Name))
                    {
                        m_ChangedFiles.Add(e.Name, e);
                    }
                }
                m_Timer.Change(m_TimerInterval, Timeout.Infinite);
            }
        }

        /// <summary>
        /// 开始监控
        /// </summary>
        public void Start()
        {
            m_FileSystemWatcher.EnableRaisingEvents = true;
            this.isPaused = false;
        }

        /// <summary>
        /// 停止
        /// </summary>
        public void Stop()
        {
            m_FileSystemWatcher.EnableRaisingEvents = false;
            this.isPaused = true;
        }

        private void OnTimer(object state)
        {
            Dictionary<string, FileSystemEventArgs> tempChangedFiles = new Dictionary<string, FileSystemEventArgs>();

            lock (m_ChangedFiles)
            {
                foreach (KeyValuePair<string, FileSystemEventArgs> changedFile in m_ChangedFiles)
                {
                    tempChangedFiles.Add(changedFile.Key, changedFile.Value);
                }
                m_ChangedFiles.Clear();
            }

            foreach (KeyValuePair<string, FileSystemEventArgs> changedFile in tempChangedFiles)
            {
                if (!Directory.Exists(changedFile.Value.FullPath))
                {
                    OnFileSystem_Changed?.Invoke(this, new ProcessedFileSystemEventArgs(changedFile.Value.ChangeType, changedFile.Value.FullPath, changedFile.Value.Name));
                }
            }
        }
    }
}